文章目的只有練習串接requset部分,不是實作。實作這樣搞,一定會出事。
products、order。建議安裝gem "figaro"。
$ rails new project_name
$ rails g scaffold product name price:integer
$ rails g model order
$ rails g controller orders
#seed
Product.create(
  name: "測試商品",
  price: 500
)
$ rails db:create db:migrate db:seed
簡易設定路徑。
  root "products#index"
  resources :products
  resources :orders
這邊直接在product#index選數量送出
  <%= form_tag orders_path, method: :post do %>
    <%= hidden_field_tag(:name, @product.name) %>
    <%= hidden_field_tag(:price, @product.price) %>
    <%= select_tag(:quantity, options_for_select([*1..4])) %>
    <%= submit_tag "送出", name: nil, class: "btn btn-primary" %>
  <% end %>
Ruby測試文件直接功能化。訂單body部分。
def order_id
  "order#{SecureRandom.uuid}" #建議自制能不重複且獨立的編號就好。
end
def packages_id
  "package#{SecureRandom.uuid}" #建議自制能不重複且獨立的編號就好。
end
def amount
  params[:quantity].to_i * params[:price].to_i
  #因為訂單簡單化,所以body的兩個amount共用。
end
def body
  @body = { amount: amount,
           currency: "TWD",
           orderId: order_id,
           packages: [ { id: packages_id,
                         amount: amount,
                         products: [ {
                         name: params[:name],
                         quantity: params[:quantity].to_i,
                         price: params[:price].to_i } ] } ],
           redirectUrls: { confirmUrl: "http://127.0.0.1:3000/confitmUrl",
                           cancelUrl: "http://127.0.0.1:3000/cancelUrl" } }
end
當然如果order有開較多欄位,也可訂單建立後save,也可以重複使用資料,才是較好作法。
訂單header部分。
private
def header_nonce
  @nonce = SecureRandom.uuid
end
def header
    get_signature()
    @header = {"Content-Type": "application/json",
          "X-LINE-ChannelId": ENV["line_pay_ChannelID"],
          "X-LINE-Authorization-Nonce": @nonce,
          "X-LINE-Authorization": @signature }
end
def get_signature
  secrect = ENV["lines_pay_ChannelSecret"]
  signature_uri = "/v3/payments/request"
  message = "#{secrect}#{signature_uri}#{@body.to_json}#{@nonce}"
  hash = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), secrect, message)
  @signature = Base64.strict_encode64(hash)
end
header_nonce、body、header因為要確保加密資料都正確,所以這三項都是before_action用實體變數固定。
  before_action :header_nonce, only:[:create]
  before_action :body, only:[:create]
  before_action :header, only:[:create]
post部分,其實跟昨天長的的幾乎一樣。def create
  response = JSON.parse(get_response.body)
  if response["returnMessage"] == "Success."
    redirect_to response["info"]["paymentUrl"]["web"]
    #這邊做直接轉址。
  else
    puts response
    #這個沒意義,應該要做怎麼處理錯誤,這邊只做印出觀察錯誤資訊。
  end
end
private
def get_response
  uri = URI.parse("https://sandbox-api-pay.line.me/v3/payments/request")
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true
  request = Net::HTTP::Post.new(uri.request_uri, @header)
  request.body = @body.to_json
  response = http.request(request)
end
基本上這樣就可以發出正確請求,取得如昨天的回傳訊息,自動轉址到付款畫面。
當然正確文件撰寫不會這樣操作,order是重要文件,不會什麼欄位都沒開,還有直接把邏輯都寫在controller應該會被宰掉,但只要開頭會了,一切就都好說。建立request一開始有功能細分好,後面的confirm與其他都幾乎是照抄,注意body的不同及回傳的重要訊息就好。
Line_pay_api簡單練習就到這邊啦!
回傳資料中transactionId與regKey等是一定要紀錄的,未來串接其他部分都會用到,另外sandbox沒有regKey回傳值。
request api中body有一個選填選項options.payment.capture是讓你選擇confirm時自動確認或要賣家手動確認,但確認完後流程一樣,但實作上就會是分歧點。我是賣家我當然設定自動確認啦!要退款等之後再說 XD!!!